import utils from './utils.js';
import md5 from 'md5';
import _ from 'lodash';
import fs from "fs";
import YAML from 'yaml'
import {
  Data
} from "../../components/index.js";
import gsCfg from '../gsCfg.js'
import {
  isV3
} from '../../components/Changelog.js';
import fetch from "node-fetch"
import mys from "./mysTool.js"
import crypto from "crypto";
const _path = process.cwd();
const DEVICE_ID = utils.randomString(32).toUpperCase();
const DEVICE_NAME = utils.randomString(_.random(1, 10));
const yamlDataUrl = `${_path}/plugins/xiaoyao-cvs-plugin/data/yaml`;
let HttpsProxyAgent = ''
// 米游社的版块

export default class miHoYoApi {
  constructor (e) {
    if (e) {
      this.e = e
      this.cookie = e.cookie
      this.userId = String(e.user_id)
      this.yuntoken = e.yuntoken
      this.devId = e.devId
      this.isOs = false;
      if (this.e?.uid) {
        if (this.e.game == 'zzz') {
          this.isOs = (this.e.uid.slice(0, -8) || 0) * 1 > 9
        } else {
          this.isOs = this.e?.uid[0] * 1 > 5
        }
      }
      this.apiMap = {
        apiWeb: mys.web_api,
        saltweb: mys.saltWeb,
        saltSign: mys.salt
      }
      if (this.isOs) {
        this.apiMap = {
          apiWeb: mys.os_web_api,
          saltweb: mys.saltWeb, //os websalt待定中
          saltSign: mys.salt
        }
      }
      // //初始化配置文件
      let data = this.getStoken(this.e.user_id);
      if (data) {
        this.cookies = `stuid=${data.stuid};stoken=${data.stoken};ltoken=${data.ltoken};`;
        if (data?.mid) {
          this.cookies = `stuid=${data.stuid};stoken=${data.stoken};mid=${data.mid};`;
        }
        this.e.cookies = this.cookies
      }
    }
    Data.createDir("", yamlDataUrl, false);
  }

  getBody (name) {
    for (let item in mys.boards) {
      if (mys.boards[item].name === name) {
        return mys.boards[item]
      }
    }
  }

  async getData (type, data = {}) {
    let gameBody = this.getBody(data.name);
    let {
      url,
      headers,
      body
    } = this.getUrl(type, gameBody, data)

    if (!url) return false
    if (data.headers) {
      headers = {
        ...headers,
        ...data.headers
      }
      delete data.headers
    }
    let param = {
      headers,
      agent: await this.getAgent(),
      timeout: 10000
    }

    if (body) {
      param.method = 'post'
      param.body = body
    } else {
      param.method = 'get'
    }
    //用于处理特殊情况
    if (data.method) {
      param.method = data.method
    }
    let response = {}
    let start = Date.now()
    try {
      response = await fetch(url, param)
    } catch (error) {
      logger.error(error.toString())
      return false
    }
    if (!response.ok) {
      Bot.logger.error(`[接口][${type}][${this.e.uid}] ${response.status} ${response.statusText}`)
      return false
    }

    let res = await response.text();
    // Bot.logger.mark(`[接口][${type}][${this.e.uid}] ${Date.now() - start}ms\n${res}`)
    if (res.startsWith('(')) {
      res = JSON.parse((res).replace(/\(|\)/g, ""))
    } else {
      res = JSON.parse(res)
    }
    if (!res) {
      Bot.logger.mark('mys接口没有返回')
      return false
    }
    if (res.retcode !== 0) {
      Bot.logger.debug(`[米游社接口][请求参数] ${url} ${JSON.stringify(param)}`)
    }
    res.api = type
    if (type == "loginByPassword") {
      res.aigis_data = JSON.parse(response.headers.get("x-rpc-aigis"))
    }
    return res
  }
  getUrl (type, board, data) {
    // if(/qrCodeLogin|qrCodeQuery|getTokenByGameToken|getCookieAccountInfoByGameToken/.test(type)) this.isOs=false;
    let urlMap = {
      userGameInfo: { //通用查询
        url: `${this.apiMap.apiWeb}/binding/api/getUserGameRolesByCookie`,
        query: `game_biz=${this.isOs ? board?.osbiz : board?.biz}`,
        types: 'sign'
      },
      isSign: board?.signUrl(data, "isSign", this.apiMap.apiWeb) || {},
      sign: board?.signUrl(data, "sign", this.apiMap.apiWeb) || {},
      home: board?.signUrl(data, "home", this.apiMap.apiWeb) || {},
      //bbs接口 hoyolab那边不是很需要 这边不进行优化处理
      bbsisSign: { //bbs 签到 （状态查询 米游币查询）
        url: `${mys.bbs_api}/apihub/sapi/getUserMissionsState`,
        types: 'bbs'
      },
      bbsSign: { //bbs讨论区签到
        url: `${mys.bbs_api}/apihub/app/api/signIn`,
        body: {
          gids: data.forumId * 1
        },
        sign: true,
        types: 'bbs'
      },
      bbsGetCaptcha: {
        url: `${mys.bbs_api}/misc/api/createVerification`,
        query: `is_high=false`,
        types: 'bbs'
      },
      bbsValidate: {
        url: `https://apiv6.geetest.com/ajax.php`,
        query: `gt=${data.gt}&challenge=${data.challenge}&lang=zh-cn&pt=3&client_type=web_mobile`,
      },
      bbsCaptchaVerify: {
        url: `${mys.bbs_api}/misc/api/verifyVerification`,
        body: {
          "geetest_challenge": data.challenge, //challenge,
          "geetest_validate": data.validate,
          "geetest_seccode": `${data.validate}|jordan`
        },
        types: 'bbs'
      },
      geeType: {
        url: `https://api.geetest.com/gettype.php`,
        query: `gt=${data.gt}`
      },
      //待定接口 用于获取用户米游社顶部的模块栏
      bbs_Businesses_url: {
        url: `${mys.bbs_api}/user/api/getUserBusinesses`,
        query: `uid={}` //????
      },
      bbsPostList: { //bbs讨论区签到
        url: `${mys.bbs_api}/post/api/getForumPostList`,
        query: `forum_id=${data.forumId}&is_good=false&is_hot=false&page_size=20&sort_type=1`,
        types: 'bbs'
      },
      bbsPostFull: { //bbs讨论区签到
        url: `${mys.bbs_api}/post/api/getPostFull`,
        query: `post_id=${data.postId}`,
        types: 'bbs'
      },
      bbsShareConf: { //bbs讨论区签到
        url: `${mys.bbs_api}/apihub/api/getShareConf`,
        query: `entity_id=${data.postId}&entity_type=1`,
        types: 'bbs'
      },
      bbsVotePost: { //bbs讨论区签到
        url: `${mys.bbs_api}/apihub/sapi/upvotePost`,
        body: {
          "post_id": data.postId,
          "is_cancel": false
        },
        types: 'bbs'
      },
      bbsGetCookie: {
        url: `${this.apiMap.apiWeb}/auth/api/getCookieAccountInfoBySToken`,
        query: `game_biz=hk4e_cn&${data.cookies}`,
        types: ''
      },
      bbsStoken: {
        url: `${this.apiMap.apiWeb}/auth/api/getMultiTokenByLoginTicket`,
        query: `login_ticket=${data.loginTicket}&token_types=3&uid=${data.loginUid}`,
        types: 'stoken'
      },
      //很抱歉由于有人恶意倒卖，不得已只能是关闭免费token了 开放免费供人使用还被恶意倒卖指责 开源确实不好弄捏
      validate: {
        url: `http://api.fuckmys.tk/geetest`,
        query: `token=${data?.getToken}&gt=${data.gt}&challenge=${data.challenge}`
      },
      cloudLogin: {
        url: `${mys.cloud_api}/hk4e_cg_cn/gamer/api/login`,
        types: 'cloud'
      },
      cloudReward: {
        url: `${mys.cloud_api}/hk4e_cg_cn/gamer/api/listNotifications`,
        query: `status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true`,
        types: 'cloud'
      },
      cloudGamer: {
        url: `${mys.cloud_api}/hk4e_cg_cn/gamer/api/ackNotification`,
        body: {
          id: data.reward_id
        },
        types: 'cloud'
      },
      cloudGet: {
        url: `${mys.cloud_api}/hk4e_cg_cn/wallet/wallet/get`,
        types: 'cloud'
      },
      authKey: {
        ///account/auth/api/genAuthKey
        url: `${this.apiMap.apiWeb}/binding/api/genAuthKey`,
        // url:`https://gameapi-account.mihoyo.com/binding/api/genAuthKey`,
        body: {
          'auth_appid': data.auth_appid ?? 'webview_gacha',//'apicdkey',// 'webview_gacha',
          'game_biz': this.isOs ? (this.e.game == 'zzz' ? 'nap_global' : 'hk4e_global') : (this.e.game == 'zzz' ? 'nap_cn' : 'hk4e_cn'),
          'game_uid': this.e.uid * 1,
          'region': this.e.region,
        },
        types: 'authKey'
      },
      getLtoken: {
        url: `${mys.pass_api}/account/auth/api/getLTokenBySToken`,
        query: `${data?.cookies?.replace(/;/g, '&')}`,
      },
      //用于手动过验证码，账号密码登录需要
      microgg: {
        url: `https://challenge.minigg.cn/manual/index.html`,
        query: `gt=${data.gt}&challenge=${data.challenge}`
      },
      microggVl: {
        url: `https://challenge.minigg.cn/manual/`,
        query: `callback=${data.challenge}`
      },
      loginByPassword: {
        url: `${mys.pass_api}/account/ma-cn-passport/app/loginByPassword`,
        body: {
          account: this.encrypt_data(data.account),
          password: this.encrypt_data(data.password)
        },
        types: 'pass'
      },
      qrCodeLogin: {
        url: `${mys.hk4_sdk}/hk4e_cn/combo/panda/qrcode/fetch`,
        body: {
          app_id: mys.app_id,
          device: data.device
        }
      },
      qrCodeQuery: {
        url: `${mys.hk4_sdk}/hk4e_cn/combo/panda/qrcode/query`,
        body: {
          app_id: mys.app_id,
          device: data.device,
          ticket: data.ticket
        }
      },
      getTokenByGameToken: {
        url: `${mys.pass_api}/account/ma-cn-session/app/getTokenByGameToken`,
        body: {
          account_id: data.uid * 1,
          game_token: data.token
        },
        types: 'pass'
      },
      getCookieAccountInfoByGameToken: {
        url: `${mys.web_api}/auth/api/getCookieAccountInfoByGameToken`,
        query: `account_id=${data.uid}&game_token=${data.token}`
      },
      createOrder: {
        url: `${mys.hk4_sdk}/hk4e_cn/mdk/atropos/api/createOrder`,
        body: {
          "special_info": "topup_center",
          "order": data.order,
          "sign": this.gen_sign(data.order)
        },
        types: 'pay'
      },
      goodsList: {
        url: `${mys.hk4_sdk}/hk4e_cn/mdk/shopwindow/shopwindow/fetchGoods`,
        body: {
          "released_flag": true,
          "game": "hk4e_cn",
          "region": "cn_gf01",
          "uid": "1",
          "account": "1"
        },
        types: 'pay'
      },
      checkOrder: {
        url: `${mys.hk4_sdk}/hk4e_cn/mdk/atropos/api/checkOrder`,
        query: `game=hk4e_cn&region=${utils.getServer(data.uid)}&order_no=${data.order_no}&uid=${data.uid}`,
        types: 'pay'
      }
    }
    if (!urlMap[type]) return false
    let {
      url,
      query = '',
      body = '',
      types = '',
      sign = ''
    } = urlMap[type]
    if (query) url += `?${query}`
    if (body) body = JSON.stringify(body)
    let headers = this.getHeaders(board, types, sign, body, query)
    return {
      url,
      headers,
      body
    }
  }

  // 签到的 headers
  getHeaders (board, type = "bbs", sign, body = {}, query = '') {
    let header = {};
    switch (type) {
      case "bbs":
        header = {
          'Cookie': this.cookies,
          "x-rpc-channel": "miyousheluodi",
          "x-rpc-auto_test": true,
          'x-rpc-device_id': DEVICE_ID,
          'x-rpc-app_version': mys.APP_VERSION,
          "x-rpc-device_model": "Mi 10",
          'x-rpc-device_name': DEVICE_NAME,
          'x-rpc-client_type': '2', // 1 - iOS, 2 - Android, 4 - Web
          'DS': (sign ? this.getDs2("", JSON.stringify({
            gids: board.forumid * 1
          }), mys.salt2) : this.getDs(mys.salt)),
          "Referer": "https://app.mihoyo.com",
          "x-rpc-sys_version": "12",
          "Host": "bbs-api.mihoyo.com",
          "User-Agent": "okhttp/4.8.0",
        }
        break;
      case "sign":
        header = {
          'accept-language': 'zh-CN,zh;q=0.9,ja-JP;q=0.8,ja;q=0.7,en-US;q=0.6,en;q=0.5',
          'x-rpc-device_id': DEVICE_ID,
          'User-Agent': `Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/${mys.APP_VERSION}`,
          Referer: board.getReferer(),
          Host: 'api-takumi.mihoyo.com',
          'x-rpc-channel': 'appstore',
          'x-rpc-app_version': mys.APP_VERSION,
          'x-requested-with': 'com.mihoyo.hyperion',
          'x-rpc-client_type': '5',
          'Content-Type': 'application/json;charset=UTF-8',
          DS: this.getDs(),
          'Cookie': this.cookie
        }
        if (board.key === "genshin") {
          header["x-rpc-signgame"] = "hk4e"
        }
        if (this.isOs) {
          let os_Header = {
            app_version: '2.9.0',
            User_Agent: `Mozilla/5.0 (Linux; Android 9.0; SAMSUNG SM-F900U Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.73 Mobile Safari/537.36 miHoYoBBSOversea/2.9.0`,
            client_type: '2',
            'x-rpc-app_version': '2.9.0',
            Origin: 'https://webstatic-sea.hoyolab.com',
            X_Requested_With: 'com.mihoyo.hoyolab',
            Referer: 'https://webstatic-sea.hoyolab.com',
            DS: this.getDs(),
            'Cookie': this.cookie
          }
          header = os_Header
        }
        break;
      case "cloud":
        header = {
          // "x-rpc-combo_token": this.yuntoken, //云原神签到ck
          // "x-rpc-client_type": "2",
          // "x-rpc-app_version": "1.3.0",
          // "x-rpc-sys_version": "11",
          // "x-rpc-channel": "mihoyo",
          // "x-rpc-device_id": this.devId, //设备Id
          // "x-rpc-device_name": "Xiaomi Mi 10 Pro",
          // "x-rpc-device_model": "Mi 10 Pro",
          // "x-rpc-app_id": "1953439974",
          // "Referer": "https://app.mihoyo.com",
          // "Content-Length": "0",
          // "Host": "api-cloudgame.mihoyo.com",
          // "Connection": "Keep-Alive",
          // "Accept-Encoding": "gzip",
          'Host': 'api-cloudgame.mihoyo.com',
          'Accept': '*/*',
          'Referer': 'https://app.mihoyo.com',
          'x-rpc-combo_token': this.yuntoken,
          'Accept-Encoding': 'gzip, deflate',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 HBPC/12.1.1.301',
          "User-Agent": "okhttp/3.14.9"
        }
        break;
      case "authKey":
        header = {
          'x-rpc-app_version': mys.APP_VERSION,
          'User-Agent': 'okhttp/4.8.0',
          'x-rpc-client_type': '5',
          Referer: 'https://app.mihoyo.com',
          Origin: 'https://webstatic.mihoyo.com',
          Cookie: this.cookies,
          DS: this.getDs(this.isOs ? mys.osSalt : mys.saltWeb),
          'x-rpc-sys_version': '12',
          'x-rpc-channel': 'mihoyo',
          'x-rpc-device_id': DEVICE_ID,
          'x-rpc-device_name': DEVICE_NAME,
          'x-rpc-device_model': 'Mi 10',
          Host: 'api-takumi.mihoyo.com'
        }
        if (this.isOs) {
          let os_Header = {
            'x-rpc-app_version': '2.18.1',
            app_version: '2.18.1',
            client_type: '2',
            'x-rpc-client_type': '2',
            Origin: 'https://app.hoyolab.com',
            X_Requested_With: 'com.mihoyo.hoyolab',
            Referer: 'https://app.hoyolab.com',
            Host: 'api-os-takumi.mihoyo.com',
            'x-rpc-channel': 'hoyolab'
          }
          header = Object.assign({}, header, os_Header)
        }
        break;
      case "stoken":
        header = {
          "x-rpc-device_id": "zxcvbnmasadfghjk123456",
          "Content-Type": "application/json;charset=UTF-8",
          "x-rpc-client_type": "",
          "x-rpc-app_version": "",
          "DS": "",
          "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/%s",
          "Referer": "cors",
          "Accept-Encoding": "gzip, deflate, br",
          "x-rpc-channel": "appstore",
        }
        break;
      case "pass":
        header = {
          'x-rpc-device_id': DEVICE_ID,
          'x-rpc-app_id': "bll8iq97cem8",
          'x-rpc-device_name': DEVICE_NAME,
          "x-rpc-device_fp": "38d7ee0e96649",
          "x-rpc-device_model": utils.randomString(16),
          'x-rpc-app_version': mys.APP_VERSION,
          'x-rpc-game_biz': 'bbs_cn',
          "x-rpc-sys_version": "11",
          "x-rpc-aigis": '',
          "Content-Type": "application/json;",
          "x-rpc-client_type": "2",
          "DS": this.getDs2('', body, mys.passSalt),
          "x-rpc-sdk_version": '1.3.1.2',
          "User-Agent": "okhttp/4.8.0",
          "Connection": 'Keep-Alive',
          "Accept-Encoding": "gzip, deflate, br",
          "x-rpc-channel": "appstore",
          Cookie: this.cookies,
        }
        break;
      case "pay":
        header = {
          "Accept": "application/json, text/plain, */*",
          "Accept-Encoding": "gzip, deflate, br",
          "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
          "Cache-Control": "no-cache",
          "Connection": "keep-alive",
          "Content-Type": "application/json;charset=UTF-8",
          "Pragma": "no-cache",
          "Referer": "https://webstatic.mihoyo.com/",
          "sec-ch-ua": '"Not?A_Brand";v="8", "Chromium";v="108", "Microsoft Edge";v="108"',
          "sec-ch-ua-mobile": "?0",
          "sec-ch-ua-platform": '"Windows"',
          "Sec-Fetch-Dest": "empty",
          "Sec-Fetch-Mode": "cors",
          "Sec-Fetch-Site": "same-site",
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54",
          "x-rpc-client_type": "4",
          "x-rpc-device_id": "3b401c79-e221-46b9-8ca5-2e072e367333",
          "x-rpc-language": "zh-cn",
          Cookie: this.cookie,
        }
        break
      default:
        header = {}
        break;
    }
    return header;
  }
  gen_sign (data) {
    if (!data) return ''
    let d = Object.keys(data).sort()
    let news = {}
    for (const item of d) {
      news[item] = data[item]
    }
    // let sign = this.HMCASHA256(Object.values(news).join(''))
    let sign = crypto.createHmac('sha256', '6bdc3982c25f3f3c38668a32d287d16b').update(Object.values(news).join('')).digest('hex')
    return sign
  }
  getStoken (userId) {
    let file = `${yamlDataUrl}/${userId}.yaml`
    try {
      let ck = fs.readFileSync(file, 'utf-8')
      ck = YAML.parse(ck)
      if (ck?.uid) {
        let datalist = {};
        ck.userId = this.e.user_id
        datalist[ck.uid] = ck;
        ck = datalist
        gsCfg.saveBingStoken(this.e.user_id, datalist)
      }
      if (!ck[this.e.uid]) {
        let user = this.e.user?.getMysUser()
        if (user.ltuid) {
          const sk = Object.values(ck).filter(i => Number(i.stuid) === Number(user.ltuid))
          if (sk?.[0]) {
            sk[0].uid = String(this.e.uid)
            sk[0].region = utils.getServer(this.e.uid, this.e.isSr)
            ck[this.e.uid] = sk[0]
            gsCfg.saveBingStoken(this.e.user_id, { [String(this.e.uid)]: sk[0] })
          }
        }
      }
      return ck[this.e.uid] || {}
    } catch (error) {
      return {}
    }
  }
  encrypt_data (data) {
    if (!data) return '';
    return crypto.publicEncrypt({
      key: mys.publicKey,
      padding: crypto.constants.RSA_PKCS1_PADDING
    }, data).toString("base64")
  }
  //社区签到ds
  getDs2 (q = "", b, salt) {
    let i = Math.floor(Date.now() / 1000)
    let r = _.random(100001, 200000)
    let add = `&b=${b}&q=${q}`
    let c = md5("salt=" + salt + "&t=" + i + "&r=" + r + add)
    return `${i},${r},${c}`
  }

  getDs (salt = mys.saltWeb) {
    const randomStr = utils.randomString(6);
    const timestamp = Math.floor(Date.now() / 1000)
    let sign = md5(`salt=${salt}&t=${timestamp}&r=${randomStr}`);
    return `${timestamp},${randomStr},${sign}`
  }

  async getAgent () {
    if (isV3) {
      let cfg = await import(`file://${_path}/lib/config/config.js`);
      let proxyAddress = cfg.default.bot.proxyAddress
      if (!proxyAddress) return null
      if (proxyAddress === 'http://0.0.0.0:0') return null

      if (!this.isOs) return null

      if (HttpsProxyAgent === '') {
        HttpsProxyAgent = await import('https-proxy-agent').catch((err) => {
          logger.error(err)
        })

        HttpsProxyAgent = HttpsProxyAgent ? HttpsProxyAgent.default : undefined
      }
      if (HttpsProxyAgent) {
        return new HttpsProxyAgent(proxyAddress)
      }
    }
    return null
  }
}
